﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;
using System.Security.AccessControl;

namespace MyLibrary.Updater
{
    public class AutoUpdater
    {
        private string configFile = "AutoUpdate.config";
        private AutoUpdaterConfig config = null;
        private bool isNeedRestart = false;
        private bool isMandatoryUpdate = false;

        public AutoUpdater()
        {
            config = AutoUpdaterConfig.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configFile));
        }

        /// <summary>
        /// 执行更新
        /// </summary>
        /// <remarks>
        /// 基本更新流程:
        /// 1.请求Web服务器,获取最新的文件列表,格式类似本地的FileList.Xml
        /// 2.远程的FileList.xml和本地的FileList.xml进行对比,生成一个更新文件列表
        /// 3.开始更新文件
        /// </remarks>
        /// <param name="IsAutoUpdate">是否为自动更新</param>
        public void Update(bool IsAutoUpdate)
        {
            try
            {
                if (IsAutoUpdate)
                {
                    if (!config.Enable)
                        return;
                }

                WebClient client = new WebClient();
                string strXml = client.DownloadString(config.ServerURL);
                Dictionary<string, RemoteFileInfo> lstRemoteFiles = ParseRemoteXml(strXml);
                List<DownloadFileInfo> lstDownloadFiles = new List<DownloadFileInfo>();
                //需要删除的文件列表
                List<LocalFileInfo> lstDeleteFiles = new List<LocalFileInfo>();
                foreach(LocalFileInfo file in config.UpdateFileList)
                {
                    if(lstRemoteFiles.ContainsKey(file.Path))
                    {
                        RemoteFileInfo rf = lstRemoteFiles[file.Path];
                        if(rf.LastVer != file.LastVersion)
                        {
                            lstDownloadFiles.Add(new DownloadFileInfo(rf.Url,file.Path,rf.LastVer,rf.Size));
                            file.LastVersion = rf.LastVer;
                            file.Size = rf.Size;

                            if(rf.NeedRestart && !isNeedRestart)
                                isNeedRestart = true;
                            if(rf.IsMandatoryUpdate && !isMandatoryUpdate)
                                isMandatoryUpdate = true;
                        }

                        lstRemoteFiles.Remove(file.Path);
                    }
                    else
                        lstDeleteFiles.Add(file);
                }

                foreach (RemoteFileInfo file in lstRemoteFiles.Values)
                {
                    lstDownloadFiles.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size));
                    config.UpdateFileList.Add(new LocalFileInfo(file.Path, file.LastVer, file.Size));

                    if (file.NeedRestart && !isNeedRestart)
                        isNeedRestart = true;
                    if (file.IsMandatoryUpdate && !isMandatoryUpdate)
                        isMandatoryUpdate = true;
                }

                if (lstDownloadFiles.Count > 0)
                {
                    //开始下载
                    //删除不需要的文件
                    foreach (LocalFileInfo file in lstDeleteFiles)
                    {
                        string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.Path);
                        if (File.Exists(filePath))
                            File.Delete(filePath);
                    }
                }
                else
                {
                    if (!IsAutoUpdate)
                    {
                    }
                }


            }
            catch
            {
            }


        }

        private Dictionary<string, RemoteFileInfo> ParseRemoteXml(string xml)
        {
            XmlDocument document = new XmlDocument();
            document.LoadXml(xml);

            Dictionary<string, RemoteFileInfo> list = new Dictionary<string, RemoteFileInfo>();
            foreach (XmlNode node in document.DocumentElement.ChildNodes)
                list.Add(node.Attributes["path"].Value, new RemoteFileInfo(node));
            return list;
        }

        /// <summary>
        /// 备份更新文件,如果更新出现异常,进行回滚用
        /// </summary>
        private void Backup()
        {
        }

        /// <summary>
        /// 更新过程错误后,进行回滚
        /// </summary>
        private void Rollback()
        {
        }
    }

}
